package com.inspur.edp.udt.designtime.webapi;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.das.commonmodel.util.HandleAssemblyNameUtil;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.element.UdtElement;
import com.inspur.edp.udt.designtime.api.exception.UdtModelErrorCodeEnum;
import com.inspur.edp.udt.designtime.api.exception.UdtModelException;
import com.inspur.edp.udt.designtime.api.extension.BaseUdtExtension;
import com.inspur.edp.udt.designtime.api.json.SimpleDataTypeDeserializer;
import com.inspur.edp.udt.designtime.api.json.SimpleDataTypeSerializer;
import com.inspur.edp.udt.designtime.api.json.UdtElementDeserializer;
import com.inspur.edp.udt.designtime.api.json.UdtElementSerializer;
import com.inspur.edp.udt.designtime.api.nocode.BusinessField;
import com.inspur.edp.udt.designtime.api.nocode.IBusinessFieldService;
import com.inspur.edp.udt.designtime.api.utils.UdtUtils;
import com.inspur.edp.udt.designtime.manager.ContentSerializer;
import com.inspur.edp.udt.designtime.manager.generatecmpcode.JavaCodeFileGenerator;
import com.inspur.edp.udt.designtime.manager.generatecomponent.ComponentGenerator;
import com.inspur.edp.udt.designtime.manager.services.UpdateAssoRefElementUtil;
import com.inspur.edp.udt.designtime.manager.services.UpdateElementService;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.util.List;
import java.util.Date;
import java.util.Map;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

@Path("")
@Produces(MediaType.APPLICATION_JSON)
public class UdtController {

  private final String SimpleUdtType = "SimpleDataType";
  private final String ComplexUdtType = "ComplexDataType";
  private com.inspur.edp.lcm.metadata.api.service.MetadataService metadataService;
  private MetadataService getMetadataService(){
    if(metadataService==null)
      metadataService= SpringBeanUtils.getBean(MetadataService.class);
    return metadataService;
  }

  /**
   * 新建UDT元数据
   * @param metadataInfo
   * @return
   */
  @Path("initial")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public String initial(String metadataInfo){
    ObjectMapper mapper=new ObjectMapper();

    try {
      JsonNode node=mapper.readTree(metadataInfo);
      String type=node.get("type").textValue();
      String metadataId=node.get("metadataId").textValue();
      String metadataName=node.get("metadataName").textValue();
      String metadataCode=node.get("metadataCode").textValue();
      String metadataAssembly=node.get("metadataAssembly").textValue();


      UnifiedDataTypeDef udt = initSimpleDataTypeDef(metadataId, metadataName, metadataCode, metadataAssembly, type);
      ContentSerializer  serializer = new ContentSerializer();
      String  udtContentJson = serializer.Serialize(udt).toString();
      return udtContentJson;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0004, e, "UnifiedDataTypeDef");
    }
  }

  private UnifiedDataTypeDef initSimpleDataTypeDef(String metadataID, String metadataName, String metadataCode, String metadataAssembly, String type)
  {
    UnifiedDataTypeDef udt;
    switch (type)
    {
      case SimpleUdtType:
        udt = new SimpleDataTypeDef();
        break;
      case ComplexUdtType:
        udt = new ComplexDataTypeDef();
        break;
      default:
        throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0005, type);
    }

    udt.setID(metadataID);
    udt.setCode(metadataCode);
    udt.setName(metadataName);
    udt.setCreatedDate(Date.from(CAFContext.current.getCurrentDateTime().toInstant()));
    udt.setModifiedDate(Date.from(CAFContext.current.getCurrentDateTime().toInstant()));
    // 20190902-wj-恢复删除初始化时AssemblyName属性上的".udt." + udt.Code
    udt.setDotnetAssemblyName(metadataAssembly+".udt."+udt.getCode());
    //udt.AssemblyName = metadataAssembly;
    return udt;
  }

  /**
   * 更新UDT关联信息
   * @param info
   * @return
   */
  @Path("updateUdtAsso")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public boolean updateUdtAsso(String info){
    ObjectMapper mapper=new ObjectMapper();

    try {
      JsonNode node=mapper.readTree(info);
      String fileName=node.get("fileName").textValue();
      String path=node.get("path").textValue();
      GspMetadata metadata=getMetadataService().loadMetadata(fileName,path);
      UpdateAssoRefElementUtil.getInstance().handleUdtAssos(metadata);

      getMetadataService().saveMetadata(metadata, UdtUtils.getCombinePath(path,metadata.getHeader().getFileName()));
      return  true;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0003, e);
    }
  }

  /**
   * 处理单值UDT关联
   * @param metadataInfo
   * @return
   */
  @Path("handleSUdtAsso")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public String handleSUdtAsso(String metadataInfo){
    ObjectMapper mapper=new ObjectMapper();
    SimpleModule module=new SimpleModule();
    module.addDeserializer(UnifiedDataTypeDef.class,new SimpleDataTypeDeserializer());
    module.addSerializer(UnifiedDataTypeDef.class,new SimpleDataTypeSerializer());
    mapper.registerModule(module);
    try {
      JsonNode node=mapper.readTree(metadataInfo);
      String elementJson=node.get("elementJson").textValue();
      SimpleDataTypeDef sUdt=mapper.readValue(elementJson,SimpleDataTypeDef.class);
      UpdateElementService.getInstance().UpdateSUdtAssos(sUdt);

      String eleJson=mapper.writeValueAsString(sUdt);
      return eleJson;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0003, e);
    }
  }

  /**
   * 处理多值UDT上的关联
   * @param metadataInfo
   * @return
   */
  @Path("handleCUdtAsso")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public String handleCUdtAsso(String metadataInfo){
    ObjectMapper mapper=new ObjectMapper();
    SimpleModule module=new SimpleModule();
    module.addSerializer(IGspCommonField.class, new UdtElementSerializer());
    module.addDeserializer(IGspCommonField.class, new UdtElementDeserializer());
    mapper.registerModule(module);
    try {
      JsonNode node=mapper.readTree(metadataInfo);
      String elementJson=node.get("elementJson").textValue();

      UdtElement udtElement= (UdtElement) mapper.readValue(elementJson, IGspCommonField.class);
      UpdateElementService.getInstance().UpdateFieldWithAsso(udtElement);
      String udtEleJson = mapper.writeValueAsString(udtElement);
      return  udtEleJson;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0003, e);
    }
  }

  /**
   * 新建UDT元数据或者打开已有元数据
   * @param metadataInfo
   * @return
   */
  @Path("handleElements")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public boolean handleElements(String metadataInfo){
    ObjectMapper mapper=new ObjectMapper();

    try {
      JsonNode node=mapper.readTree(metadataInfo);
      String fileName=node.get("fileName").textValue();
      String path=node.get("path").textValue();
      GspMetadata metadata=getMetadataService().loadMetadata(fileName,path);

      UnifiedDataTypeDef udt= (UnifiedDataTypeDef) metadata.getContent();

      if(udt instanceof SimpleDataTypeDef){
        UpdateElementService.getInstance().HandleSUdtElements((SimpleDataTypeDef) udt);
      }else if(udt instanceof ComplexDataTypeDef){
        UpdateElementService.getInstance().HandleCUdtElements((ComplexDataTypeDef) udt);
      }
      getMetadataService().saveMetadata(metadata,UdtUtils.getCombinePath(path,fileName));

      return true;

    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0003, e);
    }
  }

  /**
   * UDT元数据的保存并同步
   * @param metadataInfo
   */
  @Path("publish")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public void publish(String metadataInfo){
    ObjectMapper mapper=new ObjectMapper();

    try {
      JsonNode node=mapper.readTree(metadataInfo);
      String path=node.get("path").textValue();
      String metadataName=node.get("name").textValue();
      GspMetadata metadata=getMetadataService().loadMetadata(metadataName,path);
      String bizObjectID=metadata.getHeader().getBizobjectID();
      ComponentGenerator.getInstance().generateComponent((UnifiedDataTypeDef) metadata.getContent(),path,bizObjectID);

      new JavaCodeFileGenerator(metadata).JavaGenerate();
      getMetadataService().saveMetadata(metadata, UdtUtils.getCombinePath(path, metadata.getHeader().getFileName()));

    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0003, e);
    }
  }

  /**
   *单值/多值UDT元数据上选择udt类型
   * @param metadataInfo
   * @return
   */
  @Path("chooseUdt")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public String chooseUdt(String metadataInfo){
    ObjectMapper mapper=new ObjectMapper();

    try {
      JsonNode node=mapper.readTree(metadataInfo);
      String refUdtId=node.get("refUdtId").textValue();
      String path=node.get("path").textValue();
      String udtElementJson=node.get("udtElementJson").textValue();
      return UpdateElementService.getInstance().updateElementWithRefUdt(refUdtId, path, udtElementJson);
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0003, e);
    }
  }
  /**
   *单值/多值UDT获取ConfigId
   * @param generatingAssembly
   * @return
   */
  @Path("generatedConfigId")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public String getGeneratedConfigId(@QueryParam("generatingAssembly") String generatingAssembly)
      throws JsonProcessingException {
    if (generatingAssembly == null || generatingAssembly.isEmpty()) {
      return "";
    }
    return new ObjectMapper()
        .writeValueAsString(HandleAssemblyNameUtil.convertToJavaPackageName(generatingAssembly));
  }

  @Path("businessFields")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public List<BusinessField> getBusinessField() {
    IBusinessFieldService businessFieldService = SpringBeanUtils.getBean(IBusinessFieldService.class);
    return businessFieldService.getBusinessFields();
  }

  @Path("extendInfos")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Map<String, BaseUdtExtension> getBusinessFieldExtendInfos(@QueryParam("businessFieldId") String businessFieldId) {
    IBusinessFieldService businessFieldService = SpringBeanUtils.getBean(IBusinessFieldService.class);
    BusinessField businessField = businessFieldService.getBusinessField(businessFieldId);
    return businessField.getUnifiedDataTypeDef().getUdtExtensions();
  }

  @Path("businessFieldsByCategoryId")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public List<BusinessField> getBusinessField(@QueryParam("categoryId") String categoryId) {
    IBusinessFieldService businessFieldService = SpringBeanUtils.getBean(IBusinessFieldService.class);
    return businessFieldService.getBusinessFieldsByCategoryId(categoryId);
  }

  /**
   * 业务字段保存接口
   * @param businessField
   */
  @Path("businessField/singleasso")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public void saveBusinessField(BusinessField businessField) {
    IBusinessFieldService businessFieldService = SpringBeanUtils.getBean(IBusinessFieldService.class);
    businessFieldService.saveBusinessField(businessField);
  }
}
